#!/usr/bin/env bash
set -euo pipefail

game_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
client_dir="$game_dir/.stardew-modsync"
update_control="$game_dir/thors-fjord-update.txt"
error_log="$client_dir/last-error.log"
smapi="$game_dir/StardewModdingAPI"
mode="launch"
python_mode=()

case "${1:-}" in
  --modsync-update-only)
    mode="explicit"
    shift
    ;;
  --modsync-dry-run)
    mode="explicit"
    python_mode=(--dry-run)
    shift
    ;;
  --modsync-validate-only)
    mode="explicit"
    python_mode=(--validate-only)
    shift
    ;;
esac

write_last_error() {
  local category="$1"
  local detail_file="${2:-}"
  local pending="$client_dir/.last-error.$$.${RANDOM}.tmp"

  if {
    printf 'Thor\047s Fjord launch synchronization failed at %s\n' "$(date -u '+%Y-%m-%dT%H:%M:%SZ')"
    printf 'Category: %s\n' "$category"
    if [[ -n "$detail_file" && -f "$detail_file" ]]; then
      # Strip URL userinfo and common secret-bearing query parameters before
      # persisting diagnostics. Console output remains the synchronizer's own.
      sed -E \
        -e 's#(https?://)[^/@[:space:]]+@#\1[redacted]@#g' \
        -e 's#([?&](token|key|password|auth)=)[^&[:space:]]+#\1[redacted]#g' \
        "$detail_file"
    fi
  } >"$pending" 2>/dev/null; then
    chmod 600 "$pending" 2>/dev/null || true
    mv -f "$pending" "$error_log" 2>/dev/null || rm -f "$pending" 2>/dev/null || true
  else
    rm -f "$pending" 2>/dev/null || true
  fi
}

launch_smapi_in_macos_terminal() {
  local terminal_dir=""
  local command_file=""
  local argument

  command -v open >/dev/null 2>&1 || return 1
  terminal_dir="$(mktemp -d "${TMPDIR:-/tmp}/thors-fjord-smapi-terminal.XXXXXX" 2>/dev/null)" || return 1
  command_file="$terminal_dir/launch.command"

  if ! {
    printf '%s\n' '#!/usr/bin/env bash'
    printf 'rm -f -- %q\n' "$command_file"
    printf 'rmdir -- %q 2>/dev/null || true\n' "$terminal_dir"
    printf 'cd %q || exit $?\n' "$game_dir"
    printf 'exec %q' "$smapi"
    for argument in "$@"; do
      printf ' %q' "$argument"
    done
    printf '\n'
  } >"$command_file"; then
    rm -f "$command_file" 2>/dev/null || true
    rmdir "$terminal_dir" 2>/dev/null || true
    return 1
  fi
  chmod 700 "$command_file" || {
    rm -f "$command_file" 2>/dev/null || true
    rmdir "$terminal_dir" 2>/dev/null || true
    return 1
  }

  if [[ -d "/Applications/iTerm.app" ]]; then
    open -W -a "/Applications/iTerm.app" "$command_file"
  else
    open -W "$command_file"
  fi
  local open_status=$?
  rm -f "$command_file" 2>/dev/null || true
  rmdir "$terminal_dir" 2>/dev/null || true
  return "$open_status"
}

launch_smapi_in_linux_terminal() {
  local terminal_name="${SMAPI_PREFER_TERMINAL_NAME:-}"
  local terminal_path=""
  local candidate
  local shell_command='cd "$1" || exit $?; shift; export TERM=xterm; exec "$@"'

  if [[ -n "$terminal_name" ]]; then
    terminal_path="$(command -v -- "$terminal_name" 2>/dev/null)" || return 1
  else
    for candidate in xterm gnome-terminal kitty terminator xfce4-terminal konsole alacritty mate-terminal wezterm x-terminal-emulator; do
      if terminal_path="$(command -v -- "$candidate" 2>/dev/null)"; then
        terminal_name="$candidate"
        break
      fi
    done
  fi
  [[ -n "$terminal_path" && -x "$terminal_path" ]] || return 1

  case "$terminal_name" in
    gnome-terminal)
      exec "$terminal_path" -- "$BASH" -c "$shell_command" thors-fjord-smapi "$game_dir" "$smapi" "$@"
      ;;
    terminator|xfce4-terminal|mate-terminal)
      exec "$terminal_path" -x "$BASH" -c "$shell_command" thors-fjord-smapi "$game_dir" "$smapi" "$@"
      ;;
    wezterm)
      exec "$terminal_path" start --cwd "$game_dir" -- "$BASH" -c "$shell_command" thors-fjord-smapi "$game_dir" "$smapi" "$@"
      ;;
    kitty)
      exec "$terminal_path" "$BASH" -c "$shell_command" thors-fjord-smapi "$game_dir" "$smapi" "$@"
      ;;
    *)
      exec "$terminal_path" -e "$BASH" -c "$shell_command" thors-fjord-smapi "$game_dir" "$smapi" "$@"
      ;;
  esac
}

launch_smapi() {
  if [[ "${SMAPI_NO_TERMINAL:-}" == "true" ]]; then
    exec "$smapi" --no-terminal "$@"
  fi
  if [[ "${SMAPI_USE_CURRENT_SHELL:-}" == "true" || -t 1 ]]; then
    exec "$smapi" "$@"
  fi

  case "$(uname -s)" in
    Darwin)
      if launch_smapi_in_macos_terminal "$@"; then
        exit 0
      fi
      ;;
    Linux)
      if launch_smapi_in_linux_terminal "$@"; then
        exit 0
      fi
      ;;
  esac

  echo "A terminal could not be opened; launching SMAPI without a visible console." >&2
  exec "$smapi" "$@"
}

update_mode=""
if [[ -f "$update_control" ]]; then
  update_mode="$(tr '\r\n' '  ' < "$update_control" | tr '[:upper:]' '[:lower:]' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' -e 's/[[:space:]][[:space:]]*/ /g')" || update_mode=""
fi

if [[ "$mode" == "launch" && ! -x "$smapi" ]]; then
  echo "Installed SMAPI launcher is missing or not executable: $smapi" >&2
  exit 1
fi

if [[ "$update_mode" == "disable remote update" ]]; then
  echo "Remote mod update disabled by $update_control; using the installed mod set."
  if [[ "$mode" == "explicit" ]]; then
    exit 0
  fi
  launch_smapi "$@"
fi

if ! command -v python3 >/dev/null 2>&1; then
  echo "Python 3 is unavailable; launching the last installed mod set." >&2
  write_last_error "python3 is unavailable"
  if [[ "$mode" == "explicit" ]]; then
    exit 2
  fi
  launch_smapi "$@"
fi

if [[ "$mode" == "explicit" ]]; then
  exec python3 "$client_dir/modsync.py" --game-dir "$game_dir" "${python_mode[@]}"
fi

sync_error=""
if sync_error="$(mktemp "${TMPDIR:-/tmp}/stardew-modsync-error.XXXXXX" 2>/dev/null)"; then
  if python3 "$client_dir/modsync.py" --game-dir "$game_dir" 2>"$sync_error"; then
    rm -f "$sync_error" 2>/dev/null || true
  else
    sync_status=$?
    cat "$sync_error" >&2 || true
    echo "Thor's Fjord synchronization failed (exit $sync_status); launching the last installed mod set." >&2
    write_last_error "synchronizer exited with status $sync_status" "$sync_error"
    rm -f "$sync_error" 2>/dev/null || true
  fi
else
  # Lack of writable temporary storage must not turn a feed problem into a
  # launch blocker. Run without capture and retain a categorical diagnostic.
  if python3 "$client_dir/modsync.py" --game-dir "$game_dir"; then
    :
  else
    sync_status=$?
    echo "Thor's Fjord synchronization failed (exit $sync_status); launching the last installed mod set." >&2
    write_last_error "synchronizer exited with status $sync_status; detailed capture unavailable"
  fi
fi

launch_smapi "$@"
